/* XXL: The eXtensible and fleXible Library for data processing

Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger
                        Head of the Database Research Group
                        Department of Mathematics and Computer Science
                        University of Marburg
                        Germany

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library;  If not, see <http://www.gnu.org/licenses/>. 

    http://code.google.com/p/xxl/

*/

package xxl.core.collections.containers.recordManager;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import xxl.core.io.converters.FixedSizeConverter;

/**
 * This class is just a simple wrapping of the id Object and a recordNr.
 * So, this is used for a unique identifyer inside a RecordManager.
 * Id represents the ID of the Page in the underlying container of the strategy
 * and recordId is the position of the record in the surrounding page.
 */
public class TId {

	/**
	 * Constructs a converter for the ids generated by this container.
	 * A converter transforms an TId-Object to its byte representation and vice versa.
	 * @param idConverter The converter used for converting the 
	 * 	identifyer part of the TId.
	 * @return The converter for the TId.
	 */
	public static FixedSizeConverter getConverter(final FixedSizeConverter idConverter) {
		return new FixedSizeConverter(idConverter.getSerializedSize()+2) {
			public void write(DataOutput dataOutput, Object o) throws IOException {
				TId tid = (TId) o;
				Object o2 = tid.getId();
				idConverter.write(dataOutput, o2);
				
				dataOutput.writeShort( ((TId)o).getRecordNr() );
			}
			public Object read(DataInput dataInput, Object o) throws IOException {
				TId tid;
				if (o==null)
					tid = new TId();
				else
					tid = (TId) o;
				tid.id = idConverter.read(dataInput);
				tid.recordNr = dataInput.readShort();
				return tid;
			}
		};
	}
	
	/**
	 * The normal identifyer of the Object inside the container.
	 */
	private Object id;

	/**
	 * Record number inside the container.
	 */
	private short recordNr;

	/**
	 * Creates an instance of this class.
	 * @param id the ID of the Page in the underlying container of the strategy
	 * @param recordNr the position of the record in the corresponding page
	 */
	public TId(Object id, short recordNr) {
		this.id = id;
		this.recordNr = recordNr;
	}

	/** 
	 * Constructs an empty TId.
	 */
	private TId() {
	}

	/**
	 * Returns the ID.
	 * @return the ID
	 */
	public Object getId() {
		return id;
	}

	/**
	 * Returns the position of the record.
	 * @return the position of the record.
	 */
	public short getRecordNr() {
		return recordNr;
	}

	/**
	 * Returns a hash code for the TId. This is important if you use a TIds inside 
	 * a map. The implementation computes the XOR value of the hashCode of the
	 * id and the recordNr.
	 * @return integer value. 
	 */
	public int hashCode() {
		return id.hashCode() ^ recordNr;
	}

	/**
	 * Return true, if this Object is equal to the given Object o. False otherwise.
	 * If the given Object o isn't from the class TId, false will be returned.
	 * @param o the Object
	 * @return true, if this Object is equal to the given Object o. False otherwise.
	 */
	public boolean equals(Object o) {
		try {
			TId tid = (TId) o;
			return this.getId().equals(tid.getId())&&(this.getRecordNr()==tid.getRecordNr());
		}
		catch (Exception e) {
			return false;
		}
	}

	/**
	 * Sets the record number of the TId. 
	 * @param recordNr number of the record.
	 */
	protected void setRecordNr(short recordNr) {
		this.recordNr = recordNr;
	}

	/**
	 * Sets the identifyer of the TId. 
	 * @param id id of the record.
	 */
	protected void setId(Object id) {
		this.id = id;
	}

	/**
	 * Outputs the TId.
	 * @return a String representation of the TId.
	 */
	public String toString() {
		return "id: "+id+", recordNr:"+recordNr;
	}
}
